package graphics.main;
import game.Game;
import game.controlling.KeyListener;
import graphics.effects.Compositor;
import graphics.effects.GEExplosion;
import graphics.effects.Layer;
import graphics.effects.PartSys;
import graphics.objects.GLight;
import graphics.objects.GShape;
import graphics.objects.GraphicsObject;
import graphics.system.Color;
import graphics.system.GLTools;
import graphics.system.Renderer;
import graphics.system.TextureContainer;
import graphics.tools.Console;

import main.Config;

import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.opengl.GL20;

import tools.Floatmath;
import tools.Help;
import tools.Log;
import tools.Point;
import tools.Profiler;
public class MainRenderer extends Renderer {
	protected boolean showConsole = false;
	protected Game game;
	protected KeyListener keyListener;
	protected int frame;
	public boolean simplerender;
	protected boolean showprofiler;
	protected boolean lmb;
	public MainRenderer() {
		initializeGraphicsSystem();
		frame = 0;
		simplerender = true;
		showprofiler = false;
	}
	public void setGame(Game g) {
		game = g;
		keyListener = new KeyListener();
		g.setKeyListener(keyListener);
		g.engine.graphics.setRenderer(this);
	}
	public void handle() {
		super.handleGraphicLogic();
		game.handle();
		control();
		frame++;
	}
	protected void normalRender() {
		Layer.colormap.enable();
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0);
		Layer.colormap.clear();
		this.startCamTransformation();
		this.renderAllColor();
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
		PartSys.draw();
		this.stopCamTransformation();
		Layer.colormap.disable();
		
		generateLightMap();
		
		Layer.particles.enable();
		GL11.glClearColor(0, 0, 0, 0);
		Layer.particles.clear();
		this.startCamTransformationQualityScale(Layer.particles);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
		PartSys.drawAdditive();
		this.stopCamTransformation();
		Layer.particles.disable();		
		Layer.warp.enable();
		GL11.glClearColor(0.5f, 0.5f, 0.5f, 1);
		Layer.warp.clear();
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		this.startCamTransformationQualityScale(Layer.warp);
		this.renderAllWarp();
		this.stopCamTransformation();
		Layer.warp.disable();
		GLTools.reshape2D(width, height);
		// GL11.glClearColor(0.5f, 0.5f, 0.5f, 1);
		// GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
		Compositor.draw(width, height, zoom);
	}
	private void generateLightMap() {
		/*
		 * Layer.shadow.enable(); this.startCamTransformationQualityScale(); GL11.glClearColor(0,0,0,0); Layer.shadow.clear(); this.renderAllGlow(); this.stopCamTransformation(); Layer.shadow.disable();
		 */
		this.startCamTransformationQualityScale(Layer.shadow);
		Layer.shadow.enable();
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0);
		Layer.shadow.clear();
		GL11.glEnable(GL11.GL_STENCIL_TEST);
		int li = 0;
		for (GLight l : lights) {
			if (l.node.visible) {
				li++;
				GL11.glClearStencil(0);
				GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
				if (l.castsShadow()) {
					GL11.glColorMask(false, false, false, false);
					GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
					GL11.glStencilOp(GL11.GL_REPLACE, GL11.GL_REPLACE, GL11.GL_REPLACE);
					this.renderAllShadow(l.node.pos, l.getRadius());
					GL11.glColorMask(true, true, true, true);
					GL11.glStencilFunc(GL11.GL_EQUAL, 0, 1);
					GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
				}
				GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); // Additive blend
				l.drawGlow();
				// this.renderAllSpecular(l.node.pos, l.getRadius(), l.color);
			}
		}
		GL11.glDisable(GL11.GL_STENCIL_TEST);
		Profiler.numLights = li;
		// GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); //Additive blend
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		this.renderAllGlow();
		this.stopCamTransformation();
		Layer.shadow.disable();
		Layer.warp.enable();
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0);
		Layer.warp.clear();
		Layer.warp.disable();
		
		GLTools.blurFB(Layer.shadow, Layer.particles, 1, 3f * zoom, 1.05f, width, height);
		
		/*GL11.glClearColor(0.0f, 0.0f, 0.0f, 0);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		for (GLight l : lights) {
			if (l.node.visible) {
				Layer.warp.enable();
				Layer.warp.clear();
				this.startCamTransformationQualityScale();
				GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
				this.renderAllSpecular(l.node.pos, l.getRadius(), l.color.withAlpha(l.color.a * 0.5f));
				stopCamTransformation();
				Layer.warp.disable();
				Layer.shadow.enable();
				GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); // Additive blend
				Layer.warp.drawOnScreen((width / Config.SHADER_QUALITY) / 2, (height / Config.SHADER_QUALITY) / 2, width / Config.SHADER_QUALITY, height / Config.SHADER_QUALITY);
				Layer.shadow.disable();
			}
		}
		*/
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		/*
		 * Layer.shadow.enable(); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); //Additive blend Layer.warp.drawOnScreen(width/2, height/2, width, height); Layer.shadow.disable(); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		 */
	}
	@Override
	public void render() {
		updateVisibility();
		if (simplerender) {
			debugRender();
		}
		else {
			normalRender();
		}
		if (showConsole) {
			Console.draw();
		}
		if (showprofiler)
			Profiler.drawProfiler();
	}
	protected void debugRender() {
		GLTools.reshape2D(width, height);
		this.startCamTransformation();
		GL11.glClearColor(0.5f, 0.5f, 0.5f, 0);
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
		this.renderAllDebug();
		this.renderAllNodes();
		/*
		 * for(GLight l : lights){ if(l.node.visible){
		 * 
		 * this.renderAllShadow(l.node.pos,l.getRadius());
		 * 
		 * } }
		 */
		game.engine.drawPhysicsDebug();
		this.stopCamTransformation();
	}
	protected void control() {
		keyListener.clear();
		keyListener.mp = this.getMousePosTransformed();
		while (Keyboard.next()) {
			keyListener.addKey(Keyboard.getEventKey(), Keyboard.getEventKeyState());
			if (Keyboard.getEventKey() == Keyboard.KEY_F9 && !Keyboard.getEventKeyState()) {
				showConsole = !showConsole;
			}
			if (Keyboard.getEventKey() == Keyboard.KEY_F12 && !Keyboard.getEventKeyState()) {
				simplerender = !simplerender;
			}
			if (Keyboard.getEventKey() == Keyboard.KEY_F7 && !Keyboard.getEventKeyState()) {
				showprofiler = !showprofiler;
			}
			if (Keyboard.getEventKey() == Keyboard.KEY_F5 && !Keyboard.getEventKeyState()) {
				Log.g("reloading shader!");
				Compositor.reloadShader();
			}
		}
		float movespeed = 5;
		if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
			this.campos.y += movespeed;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
			this.campos.y -= movespeed;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
			this.campos.x += movespeed;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
			this.campos.x -= movespeed;
		}
		int wh = Mouse.getDWheel();
		if (wh < 0) {
			this.setZoom(zoom * 0.9f);
		}
		else if (wh > 0) {
			this.setZoom(zoom * 1.1f);
		}
		while (Mouse.next()) {
			keyListener.addButton(Mouse.getEventButton(), Mouse.getEventButtonState());
			if (Mouse.getEventButtonState()) {
			}
		}
		if (Mouse.isButtonDown(0)) {
			lmb = true;
		}
		if (!Mouse.isButtonDown(0) && lmb) {
			lmb = false;
		}
		if (this.keyListener.isKeyReleased(Keyboard.KEY_F8)) {
			this.takeScreenshot();
		}
	}
	public void initialize() {
		GL11.glPointSize(5);
	}
	@Override
	public int getWantedFps() {
		return game.getNetworkHandler().getWantedFps();
	}
	@Override
	public void setCurrentFps(int fps) {
		game.getNetworkHandler().setCurrentFps(fps);
	}
}
